package com.qianxun.spider.util;

import java.util.Arrays;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串工具
 * @author: huwei
 * @date: 2019/9/11 17:43
 * @version: 1.3.0
 */
public class StringUtil {
    /**
     * 将给定对象的字符串表现形式依据传入顺序串联到一起
     * @param objects 串联对象，若对象不是String类型，则取对象的String.valueOf(obj)字符串
     * @return
     */
    public static String concat(Object ...objects){
        return concatMark(null ,objects);
    }
    /**
     * 将给定对象的字符串表现形式依据传入顺序串联到一起
     * @param joinMark 连接符
     * @param objects 串联对象，若对象不是String类型，则取对象的String.valueOf(obj)字符串
     * @return
     */
    public static String concatMark(String joinMark ,Object ...objects){
        String innerJoinMark = ObjectUtil.isBlank(joinMark) ? "" : joinMark;
        StringBuffer stringBuffer = new StringBuffer();
        for(int i = 0 ;i < objects.length ;++i){
            stringBuffer.append(objects[i]).append(innerJoinMark);
        }
        //删除最后一个连接符
        stringBuffer.delete(stringBuffer.length() - innerJoinMark.length() ,stringBuffer.length());

        return stringBuffer.toString();
    }
    /**
     * 将指定字符串指定下标的字符，转换为大写
     * @param str 源字符串
     * @param index 指定下标，该下标必须在str的长度范围内才有效；
     * @return
     */
    public static String toUpperCase(String str ,int index){
        return toUpperCase(str, index ,1);
    }
    /**
     * 将指定字符串指定下标的字符，转换为大写
     * @param str 源字符串
     * @param index 指定下标，该下标必须在str的长度范围内才有效；
     * @param length 转换个数，从指定下标开始，超出str长度，以str长度为准；
     * @return
     */
    public static String toUpperCase(String str ,int index , int length){
        if(ObjectUtil.isBlank(str) || index < 0 || index >= str.length()){
            return str;
        }
        int end = length + index > str.length() || length < 1 ? str.length() : length + index;
        String target = str.substring(index ,end).toUpperCase();
        return new StringBuffer(str).delete(index ,end).insert(index ,target).toString();
    }
    /**
     * 删除指定字符串指定的前缀
     * @param str 源字符串
     * @param prefix 前缀
     * @return
     */
    public static String removePrefix(String str ,String prefix) {
        if(ObjectUtil.isBlank(str) || ObjectUtil.isBlank(prefix)){
            return str;
        }
        StringBuffer stringBuffer = new StringBuffer(str);
        while(stringBuffer.indexOf(prefix) == 0){
            stringBuffer.delete(0 ,prefix.length());
        }
        return stringBuffer.toString();
    }
    /**
     * 删除指定的后缀
     * @param str 源字符串
     * @param suffix 后缀
     * @return
     */
    public static String removeSuffix(String str ,String suffix) {
        if(ObjectUtil.isBlank(str) || ObjectUtil.isBlank(suffix)){
            return str;
        }
        StringBuffer stringBuffer = new StringBuffer(str);
        while(stringBuffer.lastIndexOf(suffix) == stringBuffer.length() - suffix.length()){
            stringBuffer.delete(stringBuffer.length() - suffix.length() ,stringBuffer.length());
        }
        return stringBuffer.toString();
    }
    /**
     * 添加前缀
     * @param str 源字符串
     * @param prefix 前缀
     * @param allLength 添加后总体长度，添加后的字符总体长度总是小于等于allLength ，出现这样的原因是：prefix 与str不能取整；
     * @return
     */
    public static String addPrefix(String str ,String prefix ,int allLength) {
        StringBuffer stringBuffer = new StringBuffer();
        while(stringBuffer.length() + prefix.length() + str.length() <= allLength) {
            stringBuffer.append(prefix);
        }
       return stringBuffer.append(str).toString();
    }
    /**
     * 添加后缀
     * @param str 源字符串
     * @param suffix 后缀
     * @param allLength 添加后总体长度，添加后的字符总体长度总是小于等于allLength ，出现这样的原因是：suffix 与str不能取整；
     * @return
     */
     public static String addSuffix(String str ,String suffix ,int allLength) {
        StringBuffer stringBuffer = new StringBuffer(str);
        while(stringBuffer.length() + suffix.length() <= allLength) {
            stringBuffer.append(suffix);
        }
        return stringBuffer.toString();
    }

    /**
     * 驼峰命令字符转指定字符链接
     * @param src 源数据
     * @param linkChar 链接字符串
     * @return
     */
    public static String camelCaseToCharLink(String src ,String linkChar) {
        StringBuffer sb = new StringBuffer();
        boolean upperCase = false;
        for (int i = 0; i < src.length(); i++) {
            char c = src.charAt(i);
            boolean nextUpperCase = true;
            if (i < (src.length() - 1)) {
                nextUpperCase = Character.isUpperCase(src.charAt(i + 1));
            }
            if ((i >= 0) && Character.isUpperCase(c)) {
                if (!upperCase || !nextUpperCase) {
                    if (i > 0){ sb.append(linkChar);}
                }
                upperCase = true;
            } else {
                upperCase = false;
            }
            sb.append(Character.toLowerCase(c));
        }
        return sb.toString();
    }

    /**
     * 将指定字符串转换为驼峰命名规则
     * @param src 源数据
     * @param linkChar 链接字符
     * @return
     */
    public static String toCamelCase(String src ,char linkChar) {
        src = src.toLowerCase();
        StringBuffer sb = new StringBuffer();
        boolean upperCase = false;
        for (int i = 0; i < src.length(); i++) {
            char c = src.charAt(i);
            if (c == linkChar) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 替换占位符，默认占位符格式${key} ,可以使用英文字符点“.”实现无限层级的值获取，示例：${user.header.eye}
     * @param str 原始字符串
     * @param evn 参数环境
     * @return
     */
    public static String replacePlaceholder(String str ,Object evn){
        return replacePlaceholder(str ,ObjectUtil.toMap(evn));
    }

    /**
     * 替换占位符 ,可以使用英文字符点“.”实现无限层级的值获取，示例：${user.header.eye}
     * @param str 原始字符串
     * @param evn 参数环境
     * @param placeholderPrefix 占位符前缀
     * @param placeholderSuffix 占位符后缀
     * @return
     */
    public static String replacePlaceholder(String str ,Object evn ,Character[] placeholderPrefix ,Character[] placeholderSuffix){
        return replacePlaceholder(str ,ObjectUtil.toMap(evn) ,placeholderPrefix ,placeholderSuffix);
    }
    /**
     * 替换占位符，默认占位符格式${key} ,可以使用英文字符点“.”实现无限层级的值获取，示例：${user.header.eye}
     * @param str 原始字符串
     * @param evn 参数环境
     * @return
     */
    public static String replacePlaceholder(String str , Map<String ,Object> evn){
        return replacePlaceholder(str, evn ,new Character[]{'$','{'} ,new Character[]{'}'});
    }
    /**
     * 替换占位符 ,可以使用英文字符点“.”实现无限层级的值获取，示例：${user.header.eye}
     * @param str 原始字符串
     * @param evn 参数环境
     * @param placeholderPrefix 占位符前缀
     * @param placeholderSuffix 占位符后缀
     * @return
     */
    public static String replacePlaceholder(String str ,Map<String ,Object> evn ,Character[] placeholderPrefix ,Character[] placeholderSuffix){
        StringBuffer placeholderPatternBuf = new StringBuffer();
        Arrays.stream(placeholderPrefix).forEach(prefix->{
            placeholderPatternBuf.append("\\").append(prefix);
        });
        placeholderPatternBuf.append("(.*?)");
        Arrays.stream(placeholderSuffix).forEach(suffix->{
            placeholderPatternBuf.append("\\").append(suffix);
        });
        Pattern pattern = Pattern.compile(placeholderPatternBuf.toString());
        String targetStr = str;
        Matcher matcher = pattern.matcher(targetStr);
        while (matcher.find()) {
            String placeholder = matcher.group();
            String placeholderKey = placeholder.substring(placeholderPrefix.length, placeholder.length() - placeholderSuffix.length).trim();
            String[] placeholderKeys = placeholderKey.split("\\.");
            Map<String ,Object> temp = evn;
            Object placeholderValue = null;
            for(int i = 0 ;i < placeholderKeys.length ;++i){
                placeholderValue = temp == null ? null : temp.get(placeholderKeys[i]);
                if(placeholderValue == null ){
                    break;
                }
                temp = ObjectUtil.toMap(placeholderValue);
            }
            if (placeholderValue != null) {
                targetStr = targetStr.replace(placeholder, placeholderValue.toString());
            }
        }
        return targetStr;
    }

    /**
     * 删除字符串中所有的空白字符
     * @param str
     * @return
     */
    public static String deleteWhitespace(String str){
        Pattern pattern = Pattern.compile("(\\p{Zs})");
        Matcher matcher = pattern.matcher(str);
        int count = 0;
        StringBuffer stringBuffer = new StringBuffer(str);
        int deleteCount = 0;
        while (matcher.find()) {
            int oldCount = deleteCount;
            int startIndex = matcher.start();
            int endIndex = matcher.end();
            if(startIndex > endIndex || startIndex - oldCount >= stringBuffer.length()){
                continue;
            }
            deleteCount += endIndex - startIndex;
            stringBuffer.delete(startIndex - oldCount, endIndex - oldCount);
        }
        return stringBuffer.toString();
    }
}
